﻿using DAO;
using DAO.Core;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Principal;
using System.Web;
using System.Web.Mvc;
using WebApplication.Core;
using WebApplication.Core.Helpers;
using WebApplication.Models;

namespace WebApplication.Controllers
{
    public class ServerObjectController : Controller
    {
        DataManager dm;
        public ServerObjectController()
        {
            dm = new DataManager();
        }

        public ActionResult ShowObject(int id)
        {
            return View(dm.ServerObjectsManager.GetById(id));
        }

        public JsonResult SvnChekout(int idApp)
        {
            if (idApp == 0)
                throw new ArgumentException("idApp");
            var application = dm.ServerObjectsManager.GetById(idApp);
            if(application == null)
                return Json(new { state = "error", message = "Нулевой объект. Объект не найден" });

            string state = "ok";
            string message = "Исходники были скачены";
            Svn svn = new Svn();

            long rev = 0;
            if (application.SvnParameter.SvnRevision != null)
                rev = (long)application.SvnParameter.SvnRevision;
            try
            {
                svn.Checkout(application.SvnParameter.SrcUrl,
                    application.SvnParameter.SvnUserName,
                    application.SvnParameter.SvnUserPassword,
                    rev,
                    application.Server.Name, application.Name);
            }
            catch (Exception ex)
            {
                state = "error";
                message = ex.Message;
            }
            
            return Json(new { state = state, message = message }, JsonRequestBehavior.AllowGet);
        }

        public ActionResult CheckIsCsProjFileNotEmpty(int idApp)
        {
            if (idApp == 0)
                throw new ArgumentException("idApp");
            var application = dm.ServerObjectsManager.GetById(idApp);
            if (!string.IsNullOrEmpty(application.MainCsProjFileName))
                return null;
            string path = AppSettingsHelper.GetSrcPath + application.Server.Name + "(" + application.Name + ")";
            List<CsProjSetting> csProjFiles = new List<CsProjSetting>();
            Directory.GetFiles(path, "*.csproj", SearchOption.AllDirectories)
                .ToList()
                .ForEach(item => 
                {
                    csProjFiles.Add(new CsProjSetting { Name = Path.GetFileName(item), Path = item });
                });
            return View(csProjFiles);
        }

        public JsonResult BuildSources(int idApp, string csProjFileName)
        {
            if (idApp == 0)
                throw new ArgumentException("idApp");
            var application = dm.ServerObjectsManager.GetById(idApp);
            if (application == null)
                return Json(new { state = "error", message = "Нулевой объект. Объект не найден" }, JsonRequestBehavior.AllowGet);
            string csProj = "";
            string state = "ok";
            string message = "Приложение построено";

            if (string.IsNullOrEmpty(application.MainCsProjFileName))
            {
                csProj = csProjFileName;
                application.MainCsProjFileName = csProjFileName;
                dm.ServerObjectsManager.Edit(application);
                dm.SaveChanges();
            }
            else
            {
                csProj = application.MainCsProjFileName;
            }
            Builder builder = new Builder();
            try
            {
                builder.BuildApplication(csProj, 
                    application.BuildParameter.BuildCommand, 
                    application.Server.Name, application.Name);
            }
            catch (Exception ex)
            {
                state = "error";
                message = ex.Message;
            }
            return Json(new { state = state, message = message }, JsonRequestBehavior.AllowGet);
        }

        public JsonResult DeployApplication(int idApp, string version)
        {
            if (idApp == 0)
                throw new ArgumentException("idApp");
            var application = dm.ServerObjectsManager.GetById(idApp);
            if (application == null)
                return Json(new { state = "error", message = "Нулевой объект. Объект не найден" }, JsonRequestBehavior.AllowGet);
            Deploy deploy = new Deploy();
            string state = "ok";
            string message = "Приложение развернуто";

            try
            {
                deploy.DeployApplication(application, Server.MapPath("~"));
                Operation operation = new Operation()
                {
                    DateOperation = DateTime.Now,
                    IdKindOperationType = (int)KindOperationsEnum.Deploy,
                    IdObject = idApp,
                    IdObjectType = (int)ObjectTypesEnum.ServerObject,
                    UserName = WindowsIdentity.GetCurrent().Name
                };
                dm.OperationManager.Add(operation);
                dm.SaveChanges();
                VersionsHistory vh = new VersionsHistory()
                {
                    IdOperation = operation.id,
                    OldValue = application.AppVersion,
                    NewValue = version,
                };
                dm.VersionsHistoryManager.Add(vh);
                dm.SaveChanges();
                application.AppVersion = version;
                dm.ServerObjectsManager.Edit(application);
                dm.SaveChanges();
                if (application.NotificationsApplications != null && application.NotificationsApplications.Count > 0)
                {
                    foreach (var item in application.NotificationsApplications)
                    {
                        EmailSenderHelper.Send(EmailTextHelper.GetNewAppVersionEmailText(application), item.Notification.Email, "Новая версия приложения");
                    }
                }
            }
            catch (Exception ex)
            {
                state = "error";
                message = ex.Message;
            }
            return Json(new { state = state, message = message }, JsonRequestBehavior.AllowGet);
        }

        public FileResult GetFile(int idApp)
        {
             if (idApp == 0)
                throw new ArgumentException("idApp");
            var application = dm.ServerObjectsManager.GetById(idApp);
            Deploy deploy = new Deploy();
            string fileName = deploy.GetZipPackagePath(application.Name, application.Server.Name);
            byte[] buff = null;

            FileStream fs = new FileStream(fileName,
                                           FileMode.Open,
                                           FileAccess.Read);
            BinaryReader br = new BinaryReader(fs);
            long numBytes = new FileInfo(fileName).Length;
            buff = br.ReadBytes((int)numBytes);
            fs.Close();
            br.Close();
            return File(buff, "application/zip", application.Name);
        }

        public void FillListNotificationListBoxes(DeployObject app)
        {
            List<SelectListItem> appItems = new List<SelectListItem>();
            if (app.NotificationsApplications != null)
            {
                foreach (var item in app.NotificationsApplications)
                {
                    appItems.Add
                        (
                            new SelectListItem
                            {
                                Text = item.Notification.Name + " " + item.Notification.Email,
                                Value = item.Notification.id.ToString()
                            }
                        );
                }
            }
            List<SelectListItem> allNotifications = new List<SelectListItem>();
            var items = dm.NotificationsManager.GetAll();
            if (items.Any())
            {
                foreach (var item in items)
                {
                    if (appItems.Any(t => t.Value == item.id.ToString()))
                        continue;
                    allNotifications.Add
                        (
                            new SelectListItem
                            {
                                Text = item.Name + " " + item.Email,
                                Value = item.id.ToString()
                            }
                        );
                }
            }
            ViewData["allNotifications"] = allNotifications;
            ViewData["appNotifications"] = appItems;
        }

        public ActionResult Edit(int id)
        {
            if (id == 0)
                throw new ArgumentException("idApp");
            var application = dm.ServerObjectsManager.GetById(id);
            if (application == null)
                return HttpNotFound();
            FillListNotificationListBoxes(application);
            return View(ServerObjectModel.ToServerObjectModel(application));
        }

        [HttpPost]
        public ActionResult Edit(ServerObjectModel app, string[] appNotifications)
        {
            if (!ModelState.IsValid)
            {
                ViewData["errors"] = "Объект сервера не валиден.";
                FillListNotificationListBoxes(app.ToEfEntity());
                return View(app);
            }
            DaoFaccade faccade = new DaoFaccade();
            app.appNotifications = appNotifications;
            faccade.UpdateDeployObject(app.ToEfEntity());
            return RedirectToAction("ShowObject", dm.ServerObjectsManager.GetById(app.Id));
        }

        public ActionResult Details(int id)
        {
            if (id == 0)
                throw new ArgumentException("id");
            return View(ServerObjectModel.ToServerObjectModel(dm.ServerObjectsManager.GetById(id)));
        }

        public ActionResult UpdateServers(bool? isGrouping, string search)
        {
            var depItems = dm.ServerObjectsManager.GetAll();
            if (isGrouping.HasValue)
                ViewData["isGrouping"] = isGrouping;
            else
            {
                ViewData["ServerObjects"] = depItems;
            }
            if (!string.IsNullOrEmpty(search))
            {
                ViewData["isGrouping"] = false;
                ViewData["ServerObjects"] = depItems.Where(t => t.Name.Contains(search));
            }
            return View(dm.ServerManager.GetAll());
        }

        public ActionResult GetAllNotDeleted()
        {
            return View(dm.ServerObjectsManager.GetAllNotDeleted());
        }
    }
}
